<template>
    <AForm ref="formRef" :labelCol="{ style: { width: lw } }" :model="model" @finish="handleSubmit" v-bind="$attrs">
        <template v-for="(item, key) in options" :key="key">
            <AFormItem :style="item.style" :wrapperCol="{ style: { width: item.wc } }" validateFirst :label="item.title"
                :name="key" :rules="getCombinedRules(item)">
                <!-- 输入框 -->
                <template v-if="!item.tag || item.tag === 'input'">
                    <AInput v-model:value="model[key]" :disabled="item.dis" :placeholder="getPlaceholder(item)"
                        :type="item.type || 'text'" :maxlength="item.max"
                        @input="handleInput(key, $event.target.value, item)">
                        <template #prefix v-if="$slots[key + '-prefix']">
                            <slot :name="key + '-prefix'"></slot>
                        </template>
                    </AInput>
                </template>

                <!-- 密码框 -->
                <template v-else-if="item.tag === 'password'">
                    <AInputPassword v-model:value="model[key]" :placeholder="getPlaceholder(item)"
                        :maxlength="item.max" />
                </template>

                <template v-else-if="item.tag === 'number'">
                    <AInputNumber v-bind="item.attrs" v-model:value="model[key]" :placeholder="getPlaceholder(item)"
                        :max="item.max">
                        <template #addonAfter v-if="$slots[key + '-suffix']">
                            <slot :name="key + '-suffix'"></slot>
                        </template>
                    </AInputNumber>
                </template>

                <!-- 文本域 -->
                <template v-else-if="item.tag === 'textarea'">
                    <ATextarea v-model:value="model[key]" :placeholder="getPlaceholder(item)" :maxlength="item.max"
                        :rows="item.rows || 4" />
                </template>

                <!-- 选择器 -->
                <template v-else-if="item.tag === 'select'">
                    <ASelect v-bind="item.attrs" :style="item.comStyle" :allowClear="item.allowClear"
                        v-model:value="model[key]" :showSearch="item.showSearch" :filterOption="item.filterOption"
                        :disabled="item.dis" :placeholder="getPlaceholder(item)" :options="item.options"
                        :mode="item.mode" />
                </template>

                <!-- 日期选择 -->
                <template v-else-if="item.tag === 'date'">
                    <ADatePicker v-model:value="model[key]" :placeholder="getPlaceholder(item)" style="width: 100%" />
                </template>

                <!-- 开关 -->
                <template v-else-if="item.tag === 'switch'">
                    <ASwitch v-model:checked="model[key]" />
                </template>

                <!-- 单选框 -->
                <template v-else-if="item.tag === 'radio'">
                    <ARadioGroup v-model:value="model[key]">
                        <ARadio v-for="option in item.options" :key="option.value" :value="option.value">
                            {{ option.label }}
                        </ARadio>
                    </ARadioGroup>
                </template>

                <!-- 复选框 -->
                <template v-else-if="item.tag === 'checkbox'">
                    <ACheckboxGroup v-model:value="model[key]">
                        <ACheckbox v-for="option in item.options" :key="option.value" :value="option.value">
                            {{ option.label }}
                        </ACheckbox>
                    </ACheckboxGroup>
                </template>

                <!-- 插槽 -->
                <template v-else-if="item.tag === 'slot'">
                    <slot :name="key"></slot>
                </template>
            </AFormItem>
        </template>

        <slot name="button">
            <AFormItem>
                <ASpace>
                    <AButton :loading="loading" type="primary" html-type="submit">
                        <template #icon v-if="$slots.buttonIcon">
                            <slot name="buttonIcon"></slot>
                        </template>
                        {{ submitText }}
                        <slot name="buttonSuffix" v-if="$slots.buttonSuffix"></slot>
                    </AButton>
                    <slot name="append"></slot>
                </ASpace>
            </AFormItem>
        </slot>
    </AForm>
</template>

<script setup>
import { ref, onUnmounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { debounce } from '@/libs/utils';

const { t } = useI18n();

/**
 * form表单引用
 */
const formRef = ref();

const props = defineProps({
    /**
     * 配置项
     */
    options: {
        type: Object,
        required: true,
        default: () => ({})
    },
    /**
     * 数据实体
     */
    model: {
        type: Object,
        required: true
    },
    /**
     * 提交按钮的文本
     */
    submitText: {
        type: String,
        default: '提交'
    },
    /**
     * laoding
     */
    loading: Boolean,
    /**
     * label宽度
     */
    lw: {
        type: String,
        default: 'auto'
    }
});

const emit = defineEmits(['submit', 'debounce-input']);

/**
 * 防抖函数存储
 */
const debounceMap = new Map();

/**
 * 获取placeholder文本
 * @param {Object} item 表单项配置
 * @returns {string} placeholder文本
 */
const getPlaceholder = item => {
    item.tag = item.tag || 'input';
    if (item.ph) {
        return item.ph.replace('[t]', item.title);
    }
    if (['textarea', 'password', 'input', 'number'].includes(item.tag))
        return t('component.inputPlaceholder', { title: item.title });
    return t('component.selectPlaceholder', { title: item.title });
};

/**
 * 合并验证规则
 * @param {Object} item 表单项配置
 * @returns {Array} 合并后的验证规则数组
 */
const getCombinedRules = (item) => {
    const rules = [...(item.rules || [])];

    if (item.required && !rules.some(rule => rule.required)) {
        rules.push({
            required: true,
            message: t('component.requiredMessage', { title: item.title || item.sub })
        });
    }

    if (item.tag != 'number' && item.max && !rules.some(rule => rule.max)) {
        rules.push({
            max: item.max,
            message: t('component.maxLengthMessage', { title: item.title || item.sub, max: item.max })
        });
    }

    if (item.min !== undefined && !rules.some(rule => rule.min)) {
        rules.push({
            min: item.min,
            message: t('component.minLengthMessage', { title: item.title || item.sub, min: item.min })
        });
    }

    return rules;
};

/**
 * 处理输入事件
 * @param {string} key 字段名
 * @param {string} value 输入值
 * @param {Object} item 表单项配置
 */
const handleInput = (key, value, item) => {
    // 如果配置了防抖功能
    if (item.debounce) {
        // 获取或创建防抖函数
        if (!debounceMap.has(key)) {
            debounceMap.set(key, debounce((fieldKey, fieldValue) => {
                emit('debounce-input', fieldKey, fieldValue);
            }, item.debounceDelay || 300));
        }

        // 调用防抖函数
        debounceMap.get(key)(key, value);
    }
};

/**
 * 暴露给父组件的方法
 */
defineExpose({
    /**
     * 验证表单并返回数据
     * @returns {Object} 表单数据
     */
    valid: async () => {
        await formRef.value.validate();
        return props.model;
    }
});

/**
 * 提交表单处理
 * @param {Object} values 表单数据
 */
const handleSubmit = (values) => {
    emit('submit', values);
};

/**
 * 清理防抖函数
 */
onUnmounted(() => {
    debounceMap.clear();
});
</script>